# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: jshin

import json
import os
import re

import google.protobuf.json_format as json_format


def clean_json(string):
  string = re.sub(r'#.*$', '', string, flags=re.M)
  string = re.sub(r'//.*$', '', string, flags=re.M)
  string = re.sub(",[ \t\r\n]+}", "}", string)
  string = re.sub(r",[ \t\r\n]+\]", "]", string)
  return string


def load_json(filename):
  assert filename is not None, filename
  assert os.path.exists(filename), filename
  config_json = None
  with open(filename) as f:
    config_json = json.loads(clean_json(f.read()))
  return config_json


def load_clean_json(filename):
  assert os.path.exists(filename), filename
  config = None
  with open(filename) as f:
    config = json.loads(clean_json(f.read()))
  return config


def print_json(config_json):
  print(json.dumps(config_json, indent=2, default=str))


def parse_json_pb(config_json, T):
  config_pb = T()
  json_format.ParseDict(config_json, config_pb, ignore_unknown_fields=True)
  return config_pb


def print_pb(config_pb):
  print(json_format.MessageToJson(config_pb, preserving_proto_field_name=True))


def load_pb(config_filename, T, *, log=True):
  if config_filename is None:
    return None

  config_json = load_json(config_filename)
  if log:
    print('config_json:')
    print_json(config_json)

  config_pb = parse_json_pb(config_json, T)
  if log:
    print('config_pb:')
    print_pb(config_pb)

  return config_pb


def load_pb_list(config_filename, T, *, log=True):
  if config_filename is None:
    return None

  config_json_list = load_json(config_filename)
  if log:
    print('config_json_list:')
    print_json(config_json_list)

  assert isinstance(config_json_list, list)
  config_pb_list = []
  for config_json in config_json_list:
    config_pb = parse_json_pb(config_json, T)
    config_pb_list.append(config_pb)
  if log:
    print('config_pb_list:')
    for config_pb in config_pb_list:
      print_pb(config_pb)

  return config_pb_list


def find(f, seq):
  """Return first item in sequence where f(item) == True."""
  for item in seq:
    if f(item):
      return item
  return None
